﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Data;
using System.Linq.Expressions;
using Dapper;
using Dapper.Extensions;

namespace CRM.Infrastructure.Repository
{

    /// <summary>
    /// 仓储基类
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public class BaseRepository<T> where T : class
    {
        protected DatabaseContext dbContext;

        #region 构造

        public BaseRepository()
        {
            dbContext = new DatabaseContext();
        }

        /// <summary>
        /// 连接字符串
        /// </summary>
        /// <param name="connectionString"></param>
        public BaseRepository(string connectionString)
        {
            dbContext = new DatabaseContext(connectionString);
        }

        /// <summary>
        /// 连接实例
        /// </summary>
        /// <param name="db"></param>
        public BaseRepository(DatabaseContext dbContext)
        {
            this.dbContext = dbContext;
        }

        #endregion

        #region 增删改查

        /// <summary>
        /// 插入
        /// </summary>
        /// <param name="Poco">实体</param>
        /// <returns></returns>
        public object Insert(T Poco) { return dbContext.Connection.Insert<T>(Poco, dbContext.Transcation); }

        /// <summary>
        /// 插入
        /// </summary>
        /// <param name="Poco">实体</param>
        /// <returns></returns>
        public object Insert(List<T> Pocos) { return dbContext.Connection.Insert<List<T>>(Pocos, dbContext.Transcation); }

        /// <summary>
        /// 更新
        /// </summary>
        /// <param name="Poco">实体</param>
        /// <returns></returns>
        public bool Update(T Poco) { return dbContext.Connection.Update<T>(Poco, dbContext.Transcation); }

        /// <summary>
        /// 删除
        /// </summary>
        /// <param name="Poco">实体</param>
        /// <returns></returns>
        public bool Delete(T Poco) { return dbContext.Connection.Delete<T>(Poco, dbContext.Transcation); }

        /// <summary>
        /// 删除所有
        /// </summary>
        /// <returns></returns>
        public bool DeleteAll() { return dbContext.Connection.DeleteAll<T>(dbContext.Transcation); }

        /// <summary>
        /// 删除
        /// </summary>
        /// <param name="primaryKey">主键</param>
        /// <returns></returns>
        public bool Delete(int primaryKey) { return dbContext.Connection.Delete<T>(primaryKey, dbContext.Transcation); }

        /// <summary>
        /// 查询单个实体
        /// </summary>
        /// <param name="primaryKey">主键</param>
        /// <returns></returns>
        public T SingleOrDefault(object primaryKey) { return dbContext.Connection.Get<T>(primaryKey, dbContext.Transcation); }

        /// <summary>
        /// 查询单个实体,如果存在多条则引发异常
        /// </summary>
        /// <param name="sql">查询语句</param>
        /// <param name="param">参数</param>
        /// <returns></returns>
        public T SingleOrDefault(string sql, object param = null) { return dbContext.Connection.QuerySingleOrDefault<T>(sql, param, dbContext.Transcation); }

        /// <summary>
        /// 查询单个实体
        /// </summary>
        /// <param name="sql">查询语句</param>
        /// <param name="param">参数</param>
        /// <returns></returns>
        public T FirstOrDefault(string sql, object param = null) { return dbContext.Connection.QueryFirstOrDefault<T>(sql, param, dbContext.Transcation); }

        /// <summary>
        /// 查询单个实体,如果存在多条则引发异常
        /// </summary>
        /// <param name="primaryKey">主键</param>
        /// <returns></returns>
        public T Single(object primaryKey) { return dbContext.Connection.Get<T>(primaryKey, dbContext.Transcation); }

        /// <summary>
        /// 查询单个实体,如果存在多条则引发异常
        /// </summary>
        /// <param name="sql">查询语句</param>
        /// <param name="param">参数</param>
        /// <returns></returns>
        public T Single(string sql, object param = null) { return dbContext.Connection.QuerySingle<T>(sql, param, dbContext.Transcation); }

        /// <summary>
        /// 查询单个实体
        /// </summary>
        /// <param name="sql">查询语句</param>
        /// <param name="param">参数</param>
        /// <returns></returns>
        public T First(string sql, object param = null) { return dbContext.Connection.QueryFirst<T>(sql, param, dbContext.Transcation); }

        /// <summary>
        /// 查询所有
        /// </summary>
        /// <returns></returns>
        public List<T> QueryAll()
        {
            return dbContext.Connection.GetAll<T>().ToList();
        }

        /// <summary>
        /// 批量查询
        /// </summary>
        /// <param name="sql">查询语句</param>
        /// <param name="param">参数</param>
        /// <returns></returns>
        public List<T> Query(string sql, object param = null) { return dbContext.Connection.Query<T>(sql, param, dbContext.Transcation).ToList(); }

        /// <summary>
        /// 批量查询
        /// </summary>
        /// <param name="page">页索引</param>
        /// <param name="itemsPerPage">每页记录</param>
        /// <param name="sql">查询语句</param>
        /// <param name="param">参数</param>
        /// <returns></returns>
        public List<T> QueryList(long page, long itemsPerPage, string sql, object param = null) { return dbContext.Connection.QueryList<T>(page, itemsPerPage, sql, param); }

        /// <summary>
        /// 分页查询
        /// </summary>
        /// <param name="pageIndex">页索引</param>
        /// <param name="pageSize">每页大小</param>
        /// <param name="sql">查询语句</param>
        /// <param name="param">参数</param>
        /// <returns></returns>
        public Page<T> Pages(long pageIndex, long pageSize, string sql, object param = null) { return dbContext.Connection.Page<T>(pageIndex, pageSize, sql, param); }

        /// <summary>
        /// 返回受影响的行数
        /// </summary>
        /// <param name="sql"></param>
        /// <param name="param"></param>
        /// <returns></returns>
        public int Execute(string sql, object param = null) { return dbContext.Connection.Execute(sql, param, dbContext.Transcation); }

        /// <summary>
        /// 执行查询，并返回查询所返回的结果集中第一行的第一列。 忽略额外的列或行。
        /// </summary>
        /// <typeparam name="K"></typeparam>
        /// <param name="sql"></param>
        /// <param name="param"></param>
        /// <returns></returns>
        public K ExecuteScalar<K>(string sql, object param = null) { return dbContext.Connection.ExecuteScalar<K>(sql, param, dbContext.Transcation); }

        /// <summary>
        /// 执行查询
        /// </summary>
        /// <param name="sql">查询语句</param>
        /// <param name="param">参数</param>
        /// <returns></returns>
        public DataTable QueryTable(string sql, object param = null)
        {
            using (IDataReader reader = dbContext.Connection.ExecuteReader(sql, param))
            {
                DataTable dt = new DataTable();
                dt.Load(reader);
                return dt;
            }
        }

        /// <summary>
        /// 批量插入
        /// 每次插入的数量最好进行测试,否则会影响性能
        /// </summary>
        /// <param name="pocos"></param>
        /// <returns></returns>
        public int BatchInsert(string sql, List<T> pocos)
        {
            return dbContext.Connection.Execute(sql, pocos, dbContext.Transcation);
        }
        #endregion


        #region 单表查询帮助方法

        /// <summary>
        /// 根据谓词表达式获取一个对象，如果没有获取到对象，则返回null
        /// </summary>
        /// <param name="predicate">谓词表达式</param>
        /// <param name="useCache">是否使用缓存</param>
        /// <returns></returns>
        public T QuerySingle(Expression<Func<T, bool>> predicate, bool useCache = false)
        {
            return dbContext.Connection.QuerySingle(predicate, buffered: useCache, transaction: dbContext.Transcation);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <typeparam name="M"></typeparam>
        /// <param name="predicate"></param>
        /// <param name="useCache"></param>
        /// <returns></returns>
        public M QuerySingle<M>(Expression<Func<M, bool>> predicate, bool useCache = false) where M : class
        {
            return dbContext.Connection.QuerySingle<M>(predicate, buffered: useCache, transaction: dbContext.Transcation);
        }
        /// <summary>
        /// 根据谓词表达式获取一个对象列表，如果没有获取到对象，则返回一个空列表
        /// </summary>
        /// <param name="predicate">谓词表达式</param>
        /// <param name="useCache">是否使用缓存</param>
        /// <returns></returns>
        public List<T> QueryList(Expression<Func<T, bool>> predicate, bool useCache = false)
        {
            return dbContext.Connection.QueryList(predicate, buffered: useCache, transaction: dbContext.Transcation);
        }
        /// <summary>
        /// 根据谓词表达式获取一个对象列表，如果没有获取到对象，则返回一个空列表
        /// </summary>
        /// <typeparam name="M"></typeparam>
        /// <param name="predicate"></param>
        /// <param name="useCache"></param>
        /// <returns></returns>
        public List<M> QueryList<M>(Expression<Func<M, bool>> predicate, bool useCache = false) where M : class
        {
            return dbContext.Connection.QueryList<M>(predicate, buffered: useCache, transaction: dbContext.Transcation);
        }

        #endregion
        /// <summary>
        /// 获取数据库连接
        /// </summary>
        /// <returns></returns>
        public DatabaseContext Database
        {
            get
            {
                return dbContext;
            }
        }
    }

}
